/**
 * Copyright (c) 2014 by it's authors. 
 * All rights reserved. See COPYING, AUTHORS.
 * 
 * This file is part of DanceMania project; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License, Version 3.
 * 
 * DanceMania is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License,
 * along with this program. If not, see http://www.gnu.org/licenses/.
 */
package com.m2dl.niptus.pathtrack;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Vibrator;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;

import com.m2dl.niptus.pathtrack.classes.CompassView;
import com.m2dl.niptus.pathtrack.classes.MapView;
import com.m2dl.niptus.pathtrack.classes.Utils;
import com.m2dl.niptus.pathtrack.db.DBAdapter;
import com.m2dl.niptus.pathtrack.step.StepService;
import com.m2dl.niptus.pathtrack.utils.Constants;

public class MainActivity extends Activity implements OnInitListener {
	private final String TAG = Constants.TAG + "." + getClass().getSimpleName();

	private Context mContext;

	/** Custom Views **/
	private MapView mMapView;
	private CompassView mCompassView;

	private TextToSpeech mTextToSpeech;

	private DBAdapter mDb;

	/** Step service **/
	private boolean mIsRunning = false;
	private int mStepValue = 0;
	private StepService mService;
	
	private ImageView mArrowLeft;
	private ImageView mArrowUp;
	private ImageView mArrowRight;
	private ImageView mArrowDown;
	
	private boolean mIsReturning = false;
	private boolean mIsArrived = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mContext = this;

		mMapView = (MapView) findViewById(R.id.map_view);
		mCompassView = (CompassView) findViewById(R.id.map_compass);
		
		mCompassView.setParent(this);

		mTextToSpeech = new TextToSpeech(this, this);
		
		// Arrows
		mArrowDown = (ImageView) findViewById(R.id.arrow_down);
		mArrowUp = (ImageView) findViewById(R.id.arrow_up);
		mArrowRight = (ImageView) findViewById(R.id.arrow_right);
		mArrowLeft = (ImageView) findViewById(R.id.arrow_left);
		
		startStepService();
	}

	@Override
	public void onInit(int status) {
		// Needed in order to initialize TextToSpeech
		if (status == TextToSpeech.SUCCESS) {
			Log.d(TAG, "Received success status code: " + status);
		} else {
			Log.d(TAG, "Received failed status code: " + status);
			finish();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection - no options menu
		switch (item.getItemId()) {
		case R.id.action_track:
			if (mMapView.returnHome()) {
				mTextToSpeech.speak("Let's go home!", TextToSpeech.QUEUE_FLUSH, null);
				mIsReturning = true;
			} else {
				mTextToSpeech.speak("Cannot go home!", TextToSpeech.QUEUE_FLUSH, null);
				mIsReturning = false;
			}
			
			break;

		case R.id.action_clear:
			mDb = new DBAdapter(mContext);
			mDb.cleanDB();
			mDb.close();
			
			// Reset steps
			resetValues();

			Utils.showToast(mContext, "Path cleared");
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onResume() {
		super.onResume();

		// Attach sensors listeners to view
		mCompassView.attachSensors();

		if (mIsRunning)
			bindStepService();
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		
		if (mIsRunning)
			unbindStepService();
	}

	@Override
	protected void onStop() {
		super.onStop();

		// Detach sensors from view
		mCompassView.detachSensors();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		if (mTextToSpeech != null) {
			mTextToSpeech.stop();
			mTextToSpeech.shutdown();
			Log.d(TAG, "TTS Destroyed");
		}
		
		if (mIsRunning)
			stopStepService();
	}

	private void startStepService() {
		mIsRunning = true;
		startService(new Intent(this, StepService.class));
	}

	private void bindStepService() {
		bindService(new Intent(this, StepService.class), mConnection, Context.BIND_AUTO_CREATE);
	}

	private void unbindStepService() {
		unbindService(mConnection);
	}

	private void stopStepService() {
		mIsRunning = false;
		if (mService != null) {
			stopService(new Intent(this, StepService.class));
		}
	}

	private void resetValues() {
		if (mService == null || !mIsRunning) {
			SharedPreferences state = getSharedPreferences("state", 0);
			SharedPreferences.Editor stateEditor = state.edit();
			stateEditor.putInt("steps", 0);
			stateEditor.commit();
		}
	}

	private ServiceConnection mConnection = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName arg0, IBinder arg1) {
			mService = ((StepService.StepBinder) arg1).getService();
			mService.registerCallback(mCallback);
		}

		@Override
		public void onServiceDisconnected(ComponentName arg0) {
			mService = null;
		}
	};

	private StepService.ICallback mCallback = new StepService.ICallback() {
		public void stepsChanged(int value) {
			mHandler.sendMessage(mHandler.obtainMessage(STEPS_MSG, value, 0));
		}
	};

	private static final int STEPS_MSG = 1;

	private Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case STEPS_MSG:
				mStepValue = (int) msg.arg1;
				mMapView.onStep();
				Utils.showToast(mContext, "Steps: " + mStepValue);
				break;
			default:
				super.handleMessage(msg);
			}
		}
	};
	
	public void showArrow(int direction) {
		if (!mIsReturning)
			return;
		
		mArrowDown.setVisibility(View.GONE);
		mArrowUp.setVisibility(View.GONE);
		mArrowLeft.setVisibility(View.GONE);
		mArrowRight.setVisibility(View.GONE);
		
		switch (direction) {
		case 0:
			mArrowUp.setVisibility(View.VISIBLE);
			break;
		case 1:
			mArrowRight.setVisibility(View.VISIBLE);
			break;
		case 2:
			mArrowDown.setVisibility(View.VISIBLE);
			break;
		case 3:
			mArrowLeft.setVisibility(View.VISIBLE);
			break;
		}
	}
	
	
	public void destinationReached() {
		if (mIsArrived)
			return;
		
		mTextToSpeech.speak("You arrived home!", TextToSpeech.QUEUE_FLUSH, null);
		((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(1000);
		mIsArrived = true;
	}
}
